package cn.gailvlun.gll.presentation.hotel.night

import android.app.Activity
import android.app.Dialog
import android.content.Context
import android.content.Intent
import android.databinding.DataBindingUtil
import android.os.Bundle
import android.support.annotation.StringDef
import android.support.v7.widget.LinearLayoutManager
import android.text.Html
import android.text.Spanned
import android.text.TextUtils
import android.view.View
import cn.gailvlun.gll.R
import cn.gailvlun.gll.bean.PlaceHolder
import cn.gailvlun.gll.databinding.ActivityHotelCommentBinding
import cn.gailvlun.gll.net.HttpMethods
import cn.gailvlun.gll.net.HttpSubscriber
import cn.gailvlun.gll.net.ListRes
import cn.gailvlun.gll.net.NewQueryParam
import cn.gailvlun.gll.net.hotel.AddInsomniaCommentReq
import cn.gailvlun.gll.net.hotel.HeartHotelCommentReq
import cn.gailvlun.gll.net.hotel.InsomniaComment
import cn.gailvlun.gll.presentation.base.App
import cn.gailvlun.gll.presentation.base.BaseActivity
import cn.gailvlun.gll.presentation.emotion.util.EmotionDateUtil
import cn.gailvlun.gll.util.*
import com.blankj.utilcode.util.KeyboardUtils
import com.github.markzhai.recyclerview.BaseViewAdapter
import com.jakewharton.rxbinding2.view.RxView
import com.jakewharton.rxbinding2.widget.RxTextView
import com.scwang.smartrefresh.layout.api.RefreshLayout
import com.scwang.smartrefresh.layout.listener.OnLoadmoreListener
import com.scwang.smartrefresh.layout.listener.OnRefreshListener
import io.reactivex.functions.Consumer
import rx_activity_result2.Result
import rx_activity_result2.RxActivityResult
import java.util.concurrent.TimeUnit

const val ORDER_TIME = "created"
const val ORDER_HOT = "heart"

@StringDef(ORDER_TIME, ORDER_HOT)
annotation class HotelCommentOrder


class HotelCommentActivity : BaseActivity(), OnRefreshListener, OnLoadmoreListener {
    companion object {
        @JvmStatic
        fun openActivity(context: Context, recordId: Int?) {
            val intent = Intent(context, HotelCommentActivity::class.java)
            intent.putExtra("recordId", recordId)
            context.startActivity(intent)
        }

        @JvmStatic
        fun openActivityFromNotification(context: Context, recordId: Int?) {
            val intent = Intent(context, HotelCommentActivity::class.java)
            intent.putExtra("recordId", recordId)
            intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
            context.startActivity(intent)
        }

        @JvmStatic
        fun openActivityForResult(activity: BaseActivity, recordId: Int?, result: Consumer<Result<BaseActivity>>) {
            val intent = Intent(activity, HotelCommentActivity::class.java)
            intent.putExtra("recordId", recordId)
            RxActivityResult.on(activity)
                    .startIntent(intent)
                    .subscribe(result)
        }
    }

    private lateinit var mBinding: ActivityHotelCommentBinding
    private var mRecordId: Int? = null
    private lateinit var mAdapter: HotelCommentAdapter
    private lateinit var mLayoutManager: LinearLayoutManager

    private val queryParam = NewQueryParam()
    private val commentReq = AddInsomniaCommentReq()
    private val replyCache: MutableMap<Int, String> = HashMap()
    @HotelCommentOrder
    private var order = ORDER_TIME

    override fun initComponent() {
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_hotel_comment)

        mAdapter = HotelCommentAdapter(mContext)
        mAdapter.setPresenter(Presenter())
        mBinding.recyclerView.adapter = mAdapter

        mLayoutManager = LinearLayoutManager(mContext)
        mBinding.recyclerView.layoutManager = mLayoutManager

        mBinding.srl.setOnRefreshListener(this)
        mBinding.srl.setOnLoadmoreListener(this)
        mBinding.srl.isEnableLoadmore = false

        mBinding.etReply.tag = -1

    }

    override fun createHandler() {
        mBinding.nbv.setOnBackListener {
            onBackPressed()
        }

        mBinding.etReply.setOnClickListener {
            if (!mBinding.etReply.isFocused) {
                commentReq.reply_id = null
                restoreReplyContent(-1)
            }
        }
        RxTextView.textChanges(mBinding.etReply).subscribe { charSequence ->
            mBinding.tvReply.isEnabled = charSequence.toString().trim().isNotEmpty()
            saveReply(charSequence.toString())
        }
        RxView.clicks(mBinding.tvReply)
                .throttleFirst(1, TimeUnit.SECONDS)
                .subscribe { replyComment(mBinding.tvReply) }

        mBinding.etReply.setOnClickListener {
            if (!mBinding.etReply.isFocused) {

                commentReq.reply_id = null

                restoreReplyContent(-1)
            }
        }
        KeyboardUtils.registerSoftInputChangedListener(this) {
            if (!KeyboardUtils.isSoftInputVisible(mContext)) {
                
                mBinding.etReply.tag = null
                mBinding.etReply.text = null
                mBinding.etReply.setHint(R.string.emotion_what_is_your_reply)
                mBinding.etReply.isFocusable = false
                mBinding.etReply.isFocusableInTouchMode = false
            }
        }
    }

    private fun saveReply(reply: String) {
        if (mBinding.etReply.tag != null) {
            replyCache.put(mBinding.etReply.tag as Int, reply)
        }
    }

    private lateinit var pd: Dialog
    private var addNum: Int = 0
    private var deleteNum: Int = 0

    private fun replyComment(v: View) {
        pd = DialogUtil.showIndeterminate(mContext)

        val text = mBinding.etReply.text.toString()
        commentReq.text = text
        commentReq.record_id = mRecordId!!

        HttpMethods.getHotelService()
                .addComment(commentReq)
                .compose(RxUtil.applyScheduler())
                .compose(bindToLifecycle())
                .subscribe(object : HttpSubscriber<InsomniaComment>() {
                    override fun onSuccess(response: InsomniaComment?) {
                        
                        mAdapter.add(0, response!!)
                        mAdapter.notifyItemInserted(0)
                        mBinding.etReply.text = null
                        commentReq.reply_id = null
                        commentReq.text = null
                        mBinding.etReply.hint = getString(R.string.hotel_comment_hint)
                        addNum += 1
                    }

                    override fun onFailure(errMsg: String?, response: InsomniaComment?, code: Int) {
                        DialogUtil.showError(mContext, errMsg)
                    }

                    override fun onComplete() {
                        super.onComplete()
                        pd.dismiss()
                    }

                })
    }

    private fun restoreReplyContent(key: Int) {
        val reply = replyCache[key]
        mBinding.etReply.isFocusable = true
        mBinding.etReply.isFocusableInTouchMode = true
        mBinding.etReply.tag = key
        if (TextUtils.isEmpty(reply)) {
            mBinding.etReply.text = null
        } else {
            mBinding.etReply.setText(reply)
            mBinding.etReply.setSelection(reply!!.length)
        }
        KeyboardUtils.showSoftInput(mBinding.etReply)
    }

    override fun loadData(savedInstanceState: Bundle?) {
        mRecordId = intent.getIntExtra("recordId", -1)

        if (mRecordId == -1) {
            ToastUtil.showShort(getString(R.string.hotel_comment_warning))
            finish()
        }

        mBinding.srl.autoRefresh()
    }

    override fun onRefresh(refreshlayout: RefreshLayout?) {
        HttpMethods.getHotelService()
                .getCommentList(order, mRecordId!!, null, null, null)
                .compose(RxUtil.applyScheduler())
                .compose(bindToLifecycle())
                .subscribe(object : HttpSubscriber<ListRes<InsomniaComment>>() {
                    override fun onSuccess(response: ListRes<InsomniaComment>?) {
                        loadRecyclerView(response?.results, true, response?.isNext)
                    }

                    override fun onFailure(errMsg: String?, response: ListRes<InsomniaComment>?, code: Int) {
                        DialogUtil.showError(mContext, errMsg)
                    }

                    override fun onFinish() {
                        super.onFinish()
                        mBinding.srl.finishRefresh()
                    }
                })
    }

    override fun onLoadmore(refreshlayout: RefreshLayout?) {
        queryParam.lastId = mAdapter.getLastId()

        HttpMethods.getHotelService()
                .getCommentList(order, mRecordId!!, queryParam.lastId, queryParam.direction, null)
                .compose(RxUtil.applyScheduler())
                .compose(bindToLifecycle())
                .subscribe(object : HttpSubscriber<ListRes<InsomniaComment>>() {
                    override fun onSuccess(response: ListRes<InsomniaComment>?) {
                        loadRecyclerView(response?.results, false, response?.isNext)
                    }

                    override fun onFailure(errMsg: String?, response: ListRes<InsomniaComment>?, code: Int) {
                        DialogUtil.showError(mContext, errMsg)
                    }

                    override fun onFinish() {
                        super.onFinish()
                        mBinding.srl.finishLoadmore()
                    }
                })
    }

    fun loadRecyclerView(list: List<InsomniaComment>?, isRefresh: Boolean, isMore: Boolean?) {
        if (isRefresh) {
            mAdapter.clear()
            if (IsEmpty.list(list)) {
            } else {
                mAdapter.addAll(list)
            }
        } else {
            mAdapter.addAll(list)
        }

        mBinding.srl.isEnableLoadmore = isMore!!
    }

    override fun onBackPressed() {

        if (addNum != deleteNum && (addNum > 0 || deleteNum > 0)) {
            val intent = Intent()






            intent.putExtra("delta", addNum - deleteNum)
            setResult(Activity.RESULT_OK, intent)
        }

        super.onBackPressed()
    }

    inner class Presenter : BaseViewAdapter.Presenter {
        fun heartComment(item: InsomniaComment) {
            val heart = if (item.heart.isHearted) -1 else 1

            val req = HeartHotelCommentReq(item.id, heart)
            HttpMethods.getHotelService()
                    .heartComment(req)
                    .compose(RxUtil.applyScheduler())
                    .compose(bindToLifecycle())
                    .subscribe(object : HttpSubscriber<InsomniaComment>() {
                        override fun onSuccess(response: InsomniaComment?) {
                            item.heart = response?.heart
                            mAdapter.notifyDataSetChanged()
                        }

                        override fun onFailure(errMsg: String?, response: InsomniaComment?, code: Int) {
                            DialogUtil.showError(mContext, errMsg)
                        }

                    })
        }

        fun replyTo(c: InsomniaComment) {
            val text = getString(R.string.emotion_comment_hint_mode, c.owner.name)
            mBinding.etReply.hint = Html.fromHtml(text)
            commentReq.reply_id = c.owner.id
            restoreReplyContent(c.id)
        }

        fun onDelete(item: InsomniaComment) {
            HttpMethods.getHotelService()
                    .deleteComment(item.id)
                    .compose(RxUtil.applyScheduler())
                    .compose(bindToLifecycle())
                    .subscribe(object : HttpSubscriber<PlaceHolder>() {
                        override fun onSuccess(response: PlaceHolder?) {
                            mAdapter.removeComment(item)
                            deleteNum += 1
                        }

                        override fun onFailure(errMsg: String?, response: PlaceHolder?, code: Int) {
                            DialogUtil.showError(mContext, errMsg)
                        }

                    })
        }
    }

    object Util {
        @JvmStatic
        fun getCommentTime(item: InsomniaComment): String {
            return EmotionDateUtil.commentTimeFormat(item.created)
        }

        @JvmStatic
        fun getCommentContent(item: InsomniaComment): Spanned {
            val focusColor = App.getInstance().resources.getColor(R.color.apricot)
            val text = if (item.reply == null)
                item.text
            else
                App.getInstance().resources.getString(R.string.emotion_comment_reply_mode,
                        focusColor,
                        item.reply.name,
                        item.text)
            return Html.fromHtml(text)
        }

        @JvmStatic
        fun getDeletionVisibility(comment: InsomniaComment): Int {
            return if (comment.owner.id == ProfileUtil.getUserId()) {
                View.VISIBLE
            } else {
                View.GONE
            }
        }
    }

    override fun onPause() {
        super.onPause()
        if (KeyboardUtils.isSoftInputVisible(mContext)) {
            KeyboardUtils.hideSoftInput(mBinding.etReply)
        }
    }

}